package cs423.loadBalancer.core;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;

import android.widget.Toast;

public class StateManager implements Runnable{

	//required implementation of the state manager
	@Override
	public void run() {

		Thread wc = new Thread(new waitConnection());
		Thread wa = new Thread(new waitAdaptor());
		
		wc.setDaemon(true);
		wa.setDaemon(true);
		
		System.out.println("THREADS INSIDE STATE MANAGER CREATED SUCCESFULLY");
		
		wc.start();
		wa.start();
		
		try {
		//	Main.sm.lock();
			Main.sm_cv.acquire();
		} catch (InterruptedException e) {
			System.out.println("Main.sm_cv.await()");
			e.printStackTrace();
		}	finally{
		//	Main.sm.unlock();
			System.out.println("FORCE CLOSE THREADS IN STATE");
			wc.stop();
			wa.stop();
		}
		
	}
	
	
	//This class waits for notification from the adaptor thread
	class waitAdaptor implements Runnable{

		@Override
		public void run() {
			while(true){
				try {
				//	Main.adaptor_tri_state_a_s_lock.lock();
					Main.adaptor_tri_state_a_s_cv.acquire();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}//	finally{
					//Main.adaptor_tri_state_a_s_lock.unlock();
				//}
				System.out.println("STATE: ACTIVE PASSING JOBS");
				
				boolean repeat = true;
				
				while(repeat){
				try {
					Socket s = new Socket(Main.ipAddress, Main.STATEPORT);
					
					OutputStream out = s.getOutputStream();
					DataOutputStream dos = new DataOutputStream(out);
					dos.writeInt(Main.STATE);
					double percentage = Main.cut_pos.size()/(double)Main.initial_q_size;
					dos.writeDouble(percentage);
			
					System.out.println("STATE: JUST ASKED FOR PERMISSION");
					
					InputStream in=null;
					in = s.getInputStream();
					DataInputStream dis = new DataInputStream(in);
					int result = dis.readInt();
					
					Main.active_transfer_decision = result;
					
					System.out.println("STATE: OTHER MACHINE SAYS "+result);
					
					Main.adaptor_tri_state_s_a_cv.release();
					repeat=false;
					s.close();
					
				} catch (UnknownHostException e) {
					System.out.println( "waiAdaptror unknowHost");					
					e.printStackTrace();
				} catch (IOException e) {
					System.out.println( "waiAdaptror IO, WILL TRY AGAIN");					
					e.printStackTrace();
					
				}
				
				}//repeat
			}
		}
		
		
	}
	
	//This thread waits for connections from the socket
	class waitConnection implements Runnable{

		@Override
		public void run() {
			ServerSocket ss=null;
			try {
				 ss = new ServerSocket(Main.STATEPORT);
			} catch (IOException e) {
				e.printStackTrace();
				System.out.println("STATE MANAGER, 92");
			}
			
			Socket OtherSide;
			try {
				while((OtherSide=ss.accept())!=null){
					InputStream in=null;
					in = OtherSide.getInputStream();
					DataInputStream dis = new DataInputStream(in);
					int result = dis.readInt();
					
					if(result==Main.STATE){
					
					System.out.println("STATE: SOME ONE WANT GIVE ME JOB");
						
					double percentage = dis.readDouble();
					Main.other_percentage = percentage;
					
					Main.state_tri_adaptor_s_a_cv.release();
					
					//Main.state_tri_adaptor_a_s_lock.lock();
					Main.state_tri_adaptor_a_s_cv.acquire();
					//Main.state_tri_adaptor_a_s_lock.unlock();
					
					int decision = Main.passive_transfer_decision;
					System.out.println("ADAPTOR DECISION IS " + decision);
					
					OutputStream out = OtherSide.getOutputStream();
					DataOutputStream dos = new DataOutputStream(out);
					dos.writeInt(decision);
					OtherSide.close();
					}
					//ELSE CONNECTION IS FROM WORKER THREAD
					else{
						/*
						//IF CONDITION ACCEPTABLE, SEND OTHER PACKETS THERE
							if(true){
							Main.trans_w_adaptor.signal();
							OutputStream out = OtherSide.getOutputStream();
							DataOutputStream dos = new DataOutputStream(out);
							dos.writeInt(Main.ALIVE);
							OtherSide.close();
							}
							*/
						//ELSE TELL THE OTHER SIDE CLOSE CONNECTION
							//else{
							Main.other_side_closed=true;
							//OutputStream out = OtherSide.getOutputStream();
							//DataOutputStream dos = new DataOutputStream(out);
							//dos.writeInt(Main.CLOSE);
							OtherSide.close();
							//}
				
					}
					
					
				}
			} catch (IOException e) {
				System.out.println( "waitconnection " + e.toString());
				e.printStackTrace();
			} catch (InterruptedException e) {
				System.out.println( "waitconnection interr" + e.toString());
				e.printStackTrace();
			}
			
		}
		
	}

}
